/**
 * 
 */
package org.sca.middle.cmpe.db;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.sca.middle.cmpe.dto.AuthCategory;
import org.sca.middle.cmpe.dto.DataTransfer;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Query;

/**
 * @author Kevin Carlen
 * @version 1.0
 */
public class AuthCategoryDAO implements DatastoreKind {

	/** The Google Datastore service */
	DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

	/** The ancestor key for AuthCategory */
	Key authTypesKey = KeyFactory.createKey(AUTHTYPES_KIND, AUTHTYPES_KEY);

	public static class LocalCacheImpl extends LocalCacheAbImpl {

		private static final LocalCacheImpl _instance = new LocalCacheImpl();

		public static LocalCacheImpl getInstance() {
			return _instance;
		}
	}
	private static final LocalCacheImpl localCache = LocalCacheImpl.getInstance();

	public AuthCategory getAuthCategory(Key key) throws NotFoundException {
		AuthCategory authCategory = (AuthCategory) localCache.getValue(key.getId());
		if (authCategory == null) {
			Entity authEntity;
			try {
				authEntity = datastore.get(key);
			} catch (EntityNotFoundException ex) {
				Logger.getLogger(AuthCategoryDAO.class.getName()).log(Level.SEVERE, null, ex);
				throw new NotFoundException(AUTHCATEGORY_KIND, key.getId());
			}
			authCategory = DataTransfer.convertAuthCategory(authEntity);
			localCache.put(key.getId(), authCategory);
		}
		return authCategory;
	}

	public AuthCategory getAuthCategory(long authCategoryId) throws NotFoundException {
		AuthCategory authCategory = (AuthCategory) localCache.getValue(new Long(authCategoryId));
		if (authCategory == null) {
			Key key = KeyFactory.createKey(authTypesKey, AUTHCATEGORY_KIND, authCategoryId);
			Entity authEntity;
			try {
				authEntity = datastore.get(key);
			} catch (EntityNotFoundException ex) {
				Logger.getLogger(AuthCategoryDAO.class.getName()).log(Level.SEVERE, null, ex);
				throw new NotFoundException(AUTHCATEGORY_KIND, authCategoryId);
			}
			authCategory = DataTransfer.convertAuthCategory(authEntity);
			localCache.put(Long.valueOf(authCategoryId), authCategory);
		}
		return authCategory;
	}

	public Key getAuthCategoryKey(AuthCategory authCategory) {
		Key key;
		Long authCategoryId = authCategory.getAuthCategoryId();
		if (authCategoryId != null && authCategoryId.longValue() > 0) {
			key = KeyFactory.createKey(authTypesKey, AUTHCATEGORY_KIND, authCategoryId);
		} else {
			key = saveAuthCategory(authCategory);
		}
		return key;
	}

	public Key getAuthCategoryKeyByDescription(String description) {
		Query.Filter descriptionFilter = new Query.FilterPredicate("description", Query.FilterOperator.EQUAL, description);
		Query query = new Query(AUTHCATEGORY_KIND, authTypesKey).setFilter(descriptionFilter);
		List<Entity> atList = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
		if (!atList.isEmpty()) {
			return atList.get(0).getKey();
		}
		return null;
	}

	public AuthCategory getAuthCategoryByDescription(String description) {
		AuthCategory at = (AuthCategory) localCache.getValue(description);
		if (at == null) {
			Query.Filter descriptionFilter = new Query.FilterPredicate("description", Query.FilterOperator.EQUAL, description);
			Query query = new Query(AUTHCATEGORY_KIND, authTypesKey).setFilter(descriptionFilter);
			List<Entity> atList = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
			if (!atList.isEmpty()) {
				at = DataTransfer.convertAuthCategory(atList.get(0));
			}
			localCache.put(description, at);
		}
		return at;
	}

	public List<AuthCategory> getAuthCategory() {
		@SuppressWarnings("unchecked")
		List<AuthCategory> atList = (List<AuthCategory>) localCache.getValue("atlist");
		if (atList == null || atList.isEmpty()) {
			Query query = new Query(AUTHCATEGORY_KIND, authTypesKey).addSort("orderValue");
			List<Entity> entityList = datastore.prepare(query).asList(FetchOptions.Builder.withDefaults());
			atList = new ArrayList<>(entityList.size());
			for (Entity entity : entityList) {
				AuthCategory newAt = DataTransfer.convertAuthCategory(entity);
				atList.add(newAt);
			}
		}
		localCache.put("atlist", atList);
		return atList;
	}

	public Key saveAuthCategory(AuthCategory authType) {
		localCache.clear();

		Entity at = null;
		if (authType.getAuthCategoryId() != null && authType.getAuthCategoryId() > 0) {
			Key authTypeKey = KeyFactory.createKey(authTypesKey, AUTHCATEGORY_KIND, authType.getAuthCategoryId());
			try {
				at = datastore.get(authTypeKey);
			} catch (EntityNotFoundException ex) {
				Logger.getLogger(AuthCategoryDAO.class.getName()).log(Level.SEVERE, null, ex);
			}
		}
		if (at == null) {
			at = new Entity(AUTHCATEGORY_KIND, authTypesKey);
		}
		at.setProperty("description", authType.getDescription());
		at.setProperty("orderValue", Integer.valueOf(authType.getOrderValue()));

		Key key = datastore.put(at);
		authType.setAuthCategoryId(Long.valueOf(key.getId()));

		return key;
	}

}
